﻿using System;
using System.Collections.Generic;
using WiMo.Games.Drawables;
using WiMo.Games.StandardCollision;

namespace WiMo.Games.StandardCollisions
{
    public class CollisionManager : ICollisionManager
    {
        private List<ISprite> _spriteList;

        Size _targetSize;

        public CollisionManager(Size targetSize)
        {
            _targetSize = targetSize;
            _spriteList = new List<ISprite>();
        }

        public void Resize(Size bounds)
        {
            _targetSize = bounds;
        }

        private CollisionManager()
        {

        }

        public void Add(ISprite sprite)
        {
            _spriteList.Add(sprite);
        }

        public void Remove(ISprite sprite)
        {
            _spriteList.Remove(sprite);
        }

        public bool DetectCollision(ISprite sprite1, ISprite sprite2)
        {
            return CollisionUtils.Collided(sprite1, sprite2);
        }

        public bool DetectSeperation(ISprite sprite1, ISprite sprite2)
        {
            return !CollisionUtils.Collided(sprite1, sprite2);
        }

        public void Update(GameTime gameTime)
        {
            foreach (var firstSprite in _spriteList)
            {
                if (!firstSprite.IsStatic)
                {
                    foreach (var secondSprite in _spriteList)
                    {
                        if (firstSprite.CanCollidesWithList.Contains(secondSprite.CollisionCategory))
                        {
                            foreach (var quad in firstSprite.Quandrants)
                            {
                                if (quad.Sprites.Contains(secondSprite))
                                    firstSprite.CheckForCollision(secondSprite);
                            }
                        }
                    }
                }
            }

            foreach (var firstSprite in _spriteList)
            {
                if (!firstSprite.IsStatic)
                {
                    foreach (var secondSprite in _spriteList)
                    {
                        firstSprite.CheckForCollision(secondSprite);
                    }
                }
            }

            foreach (var sprite in _spriteList)
            {
                if (!sprite.IsStatic)
                {
                    //for simplicity we will be working with top left
                    Location location = sprite.UnscaledPosition.Point;
                    if (sprite.Origin != Origin.TopLeft)
                        location = new Location((int)(sprite.UnscaledPosition.X - sprite.UnscaledSize.Width / 2), (int)(sprite.UnscaledPosition.Y - sprite.UnscaledSize.Height / 2));

                    PointF newLocation = PointF.Origin;
                    bool setNewLoction = false;

                    if (location.X < 0)
                    {
                        sprite.Force = new Vector2(-sprite.Force.X, sprite.Force.Y) * sprite.CoefRestitution;
                        newLocation = new PointF(0, location.Y);
                        sprite.CollideWithBorder(CollisionEventArgs.Border.Left);
                        setNewLoction = true;
                    }
                    else if (location.X + sprite.UnscaledSize.Width > _targetSize.Width)
                    {
                        sprite.Force = new Vector2(-sprite.Force.X, sprite.Force.Y) * sprite.CoefRestitution;
                        newLocation = new PointF(_targetSize.Width - sprite.UnscaledSize.Width, location.Y);
                        sprite.CollideWithBorder(CollisionEventArgs.Border.Right);
                        setNewLoction = true;
                    }

                    if (location.Y < 0)
                    {
                        sprite.Force = new Vector2(sprite.Force.X, -sprite.Force.Y) * sprite.CoefRestitution;
                        newLocation = new PointF(location.X, 0);
                        sprite.CollideWithBorder(CollisionEventArgs.Border.Top);
                        setNewLoction = true;
                    }
                    else if (location.Y + sprite.UnscaledSize.Height > _targetSize.Height)
                    {
                        sprite.Force = new Vector2(sprite.Force.X, -sprite.Force.Y) * sprite.CoefRestitution;
                        newLocation = new PointF(location.X, _targetSize.Height - sprite.UnscaledSize.Height);
                        sprite.CollideWithBorder(CollisionEventArgs.Border.Bottom);
                        setNewLoction = true;
                    }

                    ///<ducttape>
                    ///We have two modes for the position, lefttop or center.
                    ///probably a better way to do this.
                    ///</ducttape>
                    if (setNewLoction)
                    {
                        if (sprite.Origin == Origin.TopLeft)
                            sprite.Position = newLocation;
                        else
                            sprite.Position = new PointF(newLocation.X + sprite.UnscaledSize.Width / 2, newLocation.Y + sprite.UnscaledSize.Height / 2);
                    }
                }
            }

        }
    }
}


